﻿using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Linq;
using Urs.Admin.Models.Common;
using Urs.Core;
using Urs.Core.Plugins;
using Urs.Data.Domain.Configuration;
using Urs.Services.Authentication.External;
using Urs.Services.Configuration;
using Urs.Services.Localization;
using Urs.Services.Logging;
using Urs.Services.Payments;
using Urs.Services.Plugins;
using Urs.Services.Security;
using Urs.Services.Shipping;
using Urs.Framework.Controllers;
using Urs.Framework.Extensions;
using Urs.Framework.Kendoui;

namespace Urs.Admin.Controllers
{
    [AdminAuthorize]
    public partial class PluginController : BaseAdminController
    {
        #region Fields

        private readonly IPluginFinder _pluginFinder;
        private readonly ILocalizationService _localizationService;
        private readonly IActivityLogService _activityLogService;
        private readonly IWebHelper _webHelper;
        private readonly IPermissionService _permissionService;
        private readonly ISettingService _settingService;
        private readonly PaymentSettings _paymentSettings;
        private readonly ShippingSettings _shippingSettings;
        private readonly ExternalAuthSettings _externalAuthenticationSettings;
        private readonly WidgetSettings _widgetSettings;
        #endregion

        #region Constructors

        public PluginController(IPluginFinder pluginFinder,
            ILocalizationService localizationService,
            IActivityLogService activityLogService,
            IWebHelper webHelper,
            IPermissionService permissionService,
            ISettingService settingService,
            PaymentSettings paymentSettings, ShippingSettings shippingSettings,
             ExternalAuthSettings externalAuthenticationSettings,
            WidgetSettings widgetSettings)
        {
            this._pluginFinder = pluginFinder;
            this._localizationService = localizationService;
            this._webHelper = webHelper;
            this._permissionService = permissionService;
            this._activityLogService = activityLogService;
            this._settingService = settingService;
            this._paymentSettings = paymentSettings;
            this._shippingSettings = shippingSettings;
            this._externalAuthenticationSettings = externalAuthenticationSettings;
            this._widgetSettings = widgetSettings;
        }

        #endregion

        #region Utilities

        [NonAction]
        protected PluginModel PreparePluginModel(PluginDescriptor pluginDescriptor)
        {
            var pluginModel = pluginDescriptor.ToPluginModel<PluginModel>();

            pluginModel.LogoUrl = PluginManager.GetLogoUrl(pluginDescriptor);

            if (pluginDescriptor.Installed)
            {
                var pluginInstance = pluginDescriptor.Instance();
                //prepare configuration URL
                pluginModel.ConfigurationUrl = pluginInstance.GetConfigurationPageUrl();


                //enabled/disabled (only for some plugin types)
                if (pluginInstance is IPaymentMethod)
                {
                    //payment plugin
                    pluginModel.CanChangeEnabled = true;
                    pluginModel.IsEnabled = ((IPaymentMethod)pluginInstance).IsPaymentMethodActive(_paymentSettings);
                }
                else if (pluginInstance is IShippingRateMethod)
                {
                    //shipping rate computation method
                    pluginModel.CanChangeEnabled = true;
                    pluginModel.IsEnabled = ((IShippingRateMethod)pluginInstance).IsShippingRateComputationMethodActive(_shippingSettings);
                }
                else if (pluginInstance is IExternalAuthenticationMethod)
                {
                    //external auth method
                    pluginModel.CanChangeEnabled = true;
                    pluginModel.IsEnabled = ((IExternalAuthenticationMethod)pluginInstance).IsMethodActive(_externalAuthenticationSettings);
                }
                else if (pluginInstance is IWidgetPlugin)
                {
                    //Misc plugins
                    pluginModel.CanChangeEnabled = true;
                    pluginModel.IsEnabled = ((IWidgetPlugin)pluginInstance).IsWidgetActive(_widgetSettings);
                }

            }
            return pluginModel;
        }

        [NonAction]
        protected ResponseResult PreparePluginListModel()
        {
            var pluginDescriptors = _pluginFinder.GetPluginDescriptors(LoadPluginsMode.All);
            var model = new ResponseResult
            {
                data = pluginDescriptors.Select(x => PreparePluginModel(x))
                .OrderBy(x => x.Group)
                .ThenBy(x => x.DisplayOrder).ToList(),
                count = pluginDescriptors.Count()
            };
            return model;
        }

        #endregion

        #region Methods

        public IActionResult Index()
        {
            return RedirectToAction("List");
        }

        public IActionResult List()
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManagePlugins))
                return HttpUnauthorized();

            return View();
        }

        public IActionResult ListSelect(PageRequest command)
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManagePlugins))
                return HttpUnauthorized();

            var model = PreparePluginListModel();
            return Json(model);
        }
        [HttpPost]
        public IActionResult Install(IFormCollection form)
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManagePlugins))
                return HttpUnauthorized();

            try
            {
                string systemName = form["SystemName"];

                var pluginDescriptor = _pluginFinder.GetPluginDescriptorBySystemName(systemName, LoadPluginsMode.All);
                if (pluginDescriptor == null)
                    return Json(new { success = 1 });

                //check whether plugin is not installed
                if (pluginDescriptor.Installed)
                    return Json(new { success = 1 });

                //install plugin
                pluginDescriptor.Instance().Install();

                //activity log
                _activityLogService.InsertActivity("InstallNewPlugin",
                    string.Format(_localizationService.GetResource("ActivityLog.InstallNewPlugin"), pluginDescriptor.FriendlyName));

                //restart application
                _webHelper.RestartAppDomain();
            }
            catch (Exception exc)
            {
            }

            return Json(new { success = 1 });
        }

        [HttpPost]

        public IActionResult Uninstall(IFormCollection form)
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManagePlugins))
                return HttpUnauthorized();

            try
            {
                //get plugin system name
                string systemName = form["SystemName"];

                var pluginDescriptor = _pluginFinder.GetPluginDescriptorBySystemName(systemName, LoadPluginsMode.All);
                if (pluginDescriptor == null)
                    return Json(new { success = 1 });

                //check whether plugin is installed
                if (!pluginDescriptor.Installed)
                    return Json(new { success = 1 });

                //uninstall plugin
                pluginDescriptor.Instance().Uninstall();

                //activity log
                _activityLogService.InsertActivity("UninstallPlugin",
                    string.Format(_localizationService.GetResource("ActivityLog.UninstallPlugin"), pluginDescriptor.FriendlyName));

                //restart application
                _webHelper.RestartAppDomain();
            }
            catch (Exception exc)
            {
                return Json(new { error=1,msg=exc.Message });
            }

            return Json(new { success = 1 });
        }

        public IActionResult ReloadList()
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManagePlugins))
                return HttpUnauthorized();

            //restart application
            _webHelper.RestartAppDomain();
            return Json(new { success = 1 });
        }

        //edit
        public IActionResult EditPopup(string systemName)
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManagePlugins))
                return HttpUnauthorized();

            var pluginDescriptor = _pluginFinder.GetPluginDescriptorBySystemName(systemName);
            if (pluginDescriptor == null)
                return Json(new { success = 1 });

            var model = PreparePluginModel(pluginDescriptor);

            return View(model);
        }
        [HttpPost]
        public IActionResult EditPopup(PluginModel model)
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManagePlugins))
                return HttpUnauthorized();

            var pluginDescriptor = _pluginFinder.GetPluginDescriptorBySystemName(model.SystemName);
            if (pluginDescriptor == null)
                return Json(new { success = 1 });

            if (ModelState.IsValid)
            {
                //we allow editing of 'friendly name' and 'display order'
                pluginDescriptor.FriendlyName = model.FriendlyName;
                pluginDescriptor.DisplayOrder = model.DisplayOrder;
                PluginManager.SavePluginDescriptor(pluginDescriptor);
                //reset plugin cache
                _pluginFinder.ReloadPlugins(pluginDescriptor);

                //enabled/disabled
                if (pluginDescriptor.Installed)
                {
                    var pluginInstance = pluginDescriptor.Instance();
                    if (pluginInstance is IPaymentMethod)
                    {
                        //payment plugin
                        var pm = (IPaymentMethod)pluginInstance;
                        if (pm.IsPaymentMethodActive(_paymentSettings))
                        {
                            if (!model.IsEnabled)
                            {
                                //mark as disabled
                                _paymentSettings.ActivePaymentMethodSystemNames.Remove(pm.PluginDescriptor.SystemName);
                                _settingService.SaveSetting(_paymentSettings);
                            }
                        }
                        else
                        {
                            if (model.IsEnabled)
                            {
                                //mark as active
                                _paymentSettings.ActivePaymentMethodSystemNames.Add(pm.PluginDescriptor.SystemName);
                                _settingService.SaveSetting(_paymentSettings);
                            }
                        }
                    }
                    else if (pluginInstance is IShippingRateMethod)
                    {
                        //shipping rate computation method
                        var srcm = (IShippingRateMethod)pluginInstance;
                        if (srcm.IsShippingRateComputationMethodActive(_shippingSettings))
                        {
                            if (!model.IsEnabled)
                            {
                                //mark as disabled
                                _shippingSettings.ActiveShippingRateComputationMethodSystemNames.Remove(srcm.PluginDescriptor.SystemName);
                                _settingService.SaveSetting(_shippingSettings);
                            }
                        }
                        else
                        {
                            if (model.IsEnabled)
                            {
                                //mark as active
                                _shippingSettings.ActiveShippingRateComputationMethodSystemNames.Add(srcm.PluginDescriptor.SystemName);
                                _settingService.SaveSetting(_shippingSettings);
                            }
                        }
                    }
                    else if (pluginInstance is IExternalAuthenticationMethod)
                    {
                        //external auth method
                        var eam = (IExternalAuthenticationMethod)pluginInstance;
                        if (eam.IsMethodActive(_externalAuthenticationSettings))
                        {
                            if (!model.IsEnabled)
                            {
                                //mark as disabled
                                _externalAuthenticationSettings.ActiveAuthenticationMethodSystemNames.Remove(eam.PluginDescriptor.SystemName);
                                _settingService.SaveSetting(_externalAuthenticationSettings);
                            }
                        }
                        else
                        {
                            if (model.IsEnabled)
                            {
                                //mark as active
                                _externalAuthenticationSettings.ActiveAuthenticationMethodSystemNames.Add(eam.PluginDescriptor.SystemName);
                                _settingService.SaveSetting(_externalAuthenticationSettings);
                            }
                        }
                    }
                    else if (pluginInstance is IWidgetPlugin)
                    {
                        //Misc plugins
                        var widget = (IWidgetPlugin)pluginInstance;
                        if (widget.IsWidgetActive(_widgetSettings))
                        {
                            if (!model.IsEnabled)
                            {
                                //mark as disabled
                                _widgetSettings.ActiveWidgetSystemNames.Remove(widget.PluginDescriptor.SystemName);
                                _settingService.SaveSetting(_widgetSettings);
                            }
                        }
                        else
                        {
                            if (model.IsEnabled)
                            {
                                //mark as active
                                _widgetSettings.ActiveWidgetSystemNames.Add(widget.PluginDescriptor.SystemName);
                                _settingService.SaveSetting(_widgetSettings);
                            }
                        }
                    }
                }
                return Json(new { success = 1 });
            }
            return Json(new { success = 1 });
        }

        [HttpPost]
        public IActionResult IsEnabled(PluginModel model)
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManagePlugins))
                return HttpUnauthorized();

            var pluginDescriptor = _pluginFinder.GetPluginDescriptorBySystemName(model.SystemName);
            if (pluginDescriptor == null)
                return Json(new { success = 1 });

            if (ModelState.IsValid)
            {
                //enabled/disabled
                if (pluginDescriptor.Installed)
                {
                    var pluginInstance = pluginDescriptor.Instance();
                    if (pluginInstance is IPaymentMethod)
                    {
                        //payment plugin
                        var pm = (IPaymentMethod)pluginInstance;
                        if (pm.IsPaymentMethodActive(_paymentSettings))
                        {
                            if (!model.IsEnabled)
                            {
                                //mark as disabled
                                _paymentSettings.ActivePaymentMethodSystemNames.Remove(pm.PluginDescriptor.SystemName);
                                _settingService.SaveSetting(_paymentSettings);
                            }
                        }
                        else
                        {
                            if (model.IsEnabled)
                            {
                                //mark as active
                                _paymentSettings.ActivePaymentMethodSystemNames.Add(pm.PluginDescriptor.SystemName);
                                _settingService.SaveSetting(_paymentSettings);
                            }
                        }
                    }
                    else if (pluginInstance is IShippingRateMethod)
                    {
                        //shipping rate computation method
                        var srcm = (IShippingRateMethod)pluginInstance;
                        if (srcm.IsShippingRateComputationMethodActive(_shippingSettings))
                        {
                            if (!model.IsEnabled)
                            {
                                //mark as disabled
                                _shippingSettings.ActiveShippingRateComputationMethodSystemNames.Remove(srcm.PluginDescriptor.SystemName);
                                _settingService.SaveSetting(_shippingSettings);
                            }
                        }
                        else
                        {
                            if (model.IsEnabled)
                            {
                                //mark as active
                                _shippingSettings.ActiveShippingRateComputationMethodSystemNames.Add(srcm.PluginDescriptor.SystemName);
                                _settingService.SaveSetting(_shippingSettings);
                            }
                        }
                    }
                    else if (pluginInstance is IExternalAuthenticationMethod)
                    {
                        //external auth method
                        var eam = (IExternalAuthenticationMethod)pluginInstance;
                        if (eam.IsMethodActive(_externalAuthenticationSettings))
                        {
                            if (!model.IsEnabled)
                            {
                                //mark as disabled
                                _externalAuthenticationSettings.ActiveAuthenticationMethodSystemNames.Remove(eam.PluginDescriptor.SystemName);
                                _settingService.SaveSetting(_externalAuthenticationSettings);
                            }
                        }
                        else
                        {
                            if (model.IsEnabled)
                            {
                                //mark as active
                                _externalAuthenticationSettings.ActiveAuthenticationMethodSystemNames.Add(eam.PluginDescriptor.SystemName);
                                _settingService.SaveSetting(_externalAuthenticationSettings);
                            }
                        }
                    }
                    else if (pluginInstance is IWidgetPlugin)
                    {
                        //Misc plugins
                        var widget = (IWidgetPlugin)pluginInstance;
                        if (widget.IsWidgetActive(_widgetSettings))
                        {
                            if (!model.IsEnabled)
                            {
                                //mark as disabled
                                _widgetSettings.ActiveWidgetSystemNames.Remove(widget.PluginDescriptor.SystemName);
                                _settingService.SaveSetting(_widgetSettings);
                            }
                        }
                        else
                        {
                            if (model.IsEnabled)
                            {
                                //mark as active
                                _widgetSettings.ActiveWidgetSystemNames.Add(widget.PluginDescriptor.SystemName);
                                _settingService.SaveSetting(_widgetSettings);
                            }
                        }
                    }
                }
                return Json(new { success = 1 });
            }
            return Json(new { success = 1 });
        }

        #endregion
    }
}
